package com.dshore.messagecenter.service.topicQueue.impl;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.dshore.messagecenter.dao.topicqueue.QueueChartDao;
import com.dshore.messagecenter.dao.topicqueue.TopicAccessDao;
import com.dshore.messagecenter.dao.topicqueue.TopicQueueDao;
import com.dshore.messagecenter.dao.topicqueue.TopicSendDao;
import com.dshore.messagecenter.model.basedata.MdApp;
import com.dshore.messagecenter.service.topicQueue.QueueChartService;


@Service
public class QueueChartServiceimpl implements QueueChartService {
	
	@Autowired
	private QueueChartDao queueChartDao;
	@Autowired
	private TopicAccessDao topicAccessDao;
	@Autowired
	private TopicSendDao topicSendDao;
	@Autowired
	private TopicQueueDao topicQueueDao;
	
	
	/** 获取主题队列名称 */
	@Override
	public String getTopicQueueName(String tId) {
		return queueChartDao.getTopicQueueName(tId);
	}
	
	/**获取send表中多个应用的queueName(list)*/
	private List<String> getQueueNameList(String topicQueueNo) {
		return queueChartDao.getSendQueueNames(topicQueueNo);
	}
	
	/**实时内存业务逻辑(组装Map)*/
	private List<String> getKpiData(List<Map<String, Object>> currents,List<String> kpiTimes) {
		//2)内存数据集合
		List<String> kpiValues = new ArrayList<>();
	
//		System.out.println("******************************************");
		
		/**遍历时间kpiTimes集合**/
		for(int i =0; i< kpiTimes.size(); i++) { 
			String kpi = "0";
			/**1.遍历获取单条内存和时间数据 (循环将集合中时间与数据库中kpi时间进行对比) */
			for(int a=0; a<currents.size(); a++) {
				
				//单条数据
				Map<String, Object> current = currents.get(a);
//				System.out.println("------------------第" + (a+1) + "个Map数据: " + current);
				//2)单条内存数据(必须将字符串先转为 double，再除以1024后转为int，否则直接转会报错。)
				String value = current.get("KPI_VALUE").toString();
				String kpiVal = getKpiVal(value);
				/**********以上没问题*********/
				
				//1)单条时间
				String kpi_time = current.get("KPI_TIME").toString();
//				System.out.println("查询的时间字符串: " + kpi_time);
				//集合中单条时间
				String listTime = kpiTimes.get(i);
				
				//判断时间与list中时间是否一致
				if(kpi_time.equals(listTime)) {
					kpi = kpiVal;//单位KB
				}
			}
//			System.out.println("-------------------");
//			System.out.println("第" + (i+1) + "次的kpi值: " + kpi);
			//给list中添加内存数据
			kpiValues.add(kpi);
//			System.out.println("第" + (i+1) + "次添加过后的list: " + kpiValues);
//			System.out.println("\n");
		}
		
//		System.out.println("******************************************");

//		System.out.println("数据集合: " + kpiValues);
		
		return kpiValues;
	}
	
	/**获取单条kpi数据(单位: KB)*/
	private String getKpiVal(String value) {
		BigDecimal b1 = new BigDecimal(value);
		BigDecimal b2 = new BigDecimal("1024");
//		double kpiVal = b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP).doubleValue();//转为KB
		String kpiVal = String.valueOf( Math.round(b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP).doubleValue()) );
		return kpiVal;
	}
	
	/** 获取对比时间集合(公共代码) */
	private List<String> getKpiTimes() {
		SimpleDateFormat df = new SimpleDateFormat("HH:mm");
		List<String> kpiTimes = new ArrayList<>();
		for(int i=6; i>=0; i--) {
			Calendar calendar = Calendar.getInstance();
			calendar.add(calendar.MINUTE, -(5 * i));
//			System.out.println(date);
			int hour = calendar.get(Calendar.HOUR_OF_DAY);
			int minute = (calendar.get(Calendar.MINUTE) / 5) * 5;
			
			//转换格式
			df.applyPattern("HH:mm");
			Date date = null;
			try {
				date = df.parse(hour + ":" + minute);
			} catch (ParseException e) {
				e.printStackTrace();
			}
			//将秒钟转为HH:mm格式(防止秒钟为单数)
			String oneTime = df.format(date);
			
//			System.out.println(oneTime);
			kpiTimes.add(oneTime);
		}
		return kpiTimes;
	}
	
	/** 1)具体队列的实时消息流量表 */
	@Override
	public Map<String, List<String>> getOneMsgFlow(String tId, String topicQueueNo) {
		//当前时间 (end)
		Date today = new Date();
		//30分钟后(即当前时间)
		SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String end = sdf.format(today);
		
		//30分钟前时间 (start)
		long times = 35 * 60 * 1000;//35分钟的毫秒值
		Date before = new Date(today.getTime() - times); //35分钟前的时间
		String start = sdf.format(before);
//		System.out.println("开始时间： " + start + ", 结束时间: " + end);
		
		//2.获取消息发送延时数据集合
		List<Map<String, Object>> currents = queueChartDao.getMsgFlowAndTime(topicQueueNo,start,end);
		//返回前端数据Map
		Map<String, List<String>> map = new HashMap<>();
			
		//1)时间集合
		List<String> kpiTimes = getKpiTimes();//2)内存数据集合
		List<String> kpiValues = new ArrayList<>();
	
//		System.out.println("******************************************");
		
		/**遍历时间kpiTimes集合**/
		for(int i =0; i< kpiTimes.size(); i++) { 
			String kpi = "0";
			/**1.遍历获取单条内存和时间数据 (循环将集合中时间与数据库中kpi时间进行对比) */
			for(int a=0; a<currents.size(); a++) {
				
				//单条数据
				Map<String, Object> current = currents.get(a);
				String value = current.get("KPI_VALUE").toString();
				
				//1)单条时间
				String kpi_time = current.get("KPI_TIME").toString();
				//集合中单条时间
				String listTime = kpiTimes.get(i);
				
				//判断时间与list中时间是否一致
				if(kpi_time.equals(listTime)) {
					kpi = value;//单位KB
				}
			}
			//给list中添加内存数据
			kpiValues.add(kpi);
		}
		map.put("kpiTimes", kpiTimes);
		map.put("kpiValues", kpiValues);
//		System.out.println("实时消息发送延时Map数据: " + map);
		return map;
	}

	/** 2)具体队列的实时消息发送延时 */
	@Override
	public Map<String, List<String>> getOneMsgSendDelay(String tId, String topicQueueNo) {
		//当前时间 (end)
		Date today = new Date();
		//30分钟后(即当前时间)
		DateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String end = sdf.format(today);
		
		//30分钟前时间 (start)
		long times = 35 * 60 * 1000;//35分钟的毫秒值
		Date before = new Date(today.getTime() - times); //35分钟前的时间
		String start = sdf.format(before);
//		System.out.println("开始时间： " + start + ", 结束时间: " + end);
		
		//2.获取消息发送延时数据集合
		List<Map<String, Object>> currents = queueChartDao.getMsgSDAndTime(topicQueueNo,start,end);
		//返回前端数据Map
		Map<String, List<String>> map = new HashMap<>();
			
		//1)时间集合
		List<String> kpiTimes = getKpiTimes();//2)内存数据集合
		List<String> kpiValues = new ArrayList<>();
	
//		System.out.println("******************************************");
		
		/**遍历时间kpiTimes集合**/
		for(int i =0; i< kpiTimes.size(); i++) { 
			String kpi = "0";
			/**1.遍历获取单条内存和时间数据 (循环将集合中时间与数据库中kpi时间进行对比) */
			for(int a=0; a<currents.size(); a++) {
				
				//单条数据
				Map<String, Object> current = currents.get(a);
				String value = current.get("KPI_VALUE").toString();
				
				//1)单条时间
				String kpi_time = current.get("KPI_TIME").toString();
				//集合中单条时间
				String listTime = kpiTimes.get(i);
				
				//判断时间与list中时间是否一致
				if(kpi_time.equals(listTime)) {
					kpi = value;//单位KB
				}
			}
			//给list中添加内存数据
			kpiValues.add(kpi);
		}
		map.put("kpiTimes", kpiTimes);
		map.put("kpiValues", kpiValues);
//		System.out.println("实时消息发送延时数据: " + kpiValues);
		return map;
	}
	
	
	/** 3)获取具体队列的内存实时占用情况*/
	@Override
	public Map<String, List<String>> getOneMemoryStatus(String tId, String topicQueueNo) {
		//1.获取send表中多个应用的queueName(list)
		List<String> queueNames = getQueueNameList(topicQueueNo);
//		System.out.println("目标应用的queueName集合：" + queueNames);
		//list转为数组
		String[] qNames =  queueNames.toArray(new String[queueNames.size()]);
//		System.out.println("数组qNames: " + Arrays.toString(qNames));
		
		//当前时间 (end)
		Date today = new Date();
		//30分钟后(即当前时间)
		DateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String end = sdf.format(today);
		
		//30分钟前时间 (start)
		long times = 35 * 60 * 1000;//35分钟的毫秒值
		Date before = new Date(today.getTime() - times); //35分钟前的时间
		String start = sdf.format(before);
//		System.out.println("开始时间： " + start + ", 结束时间: " + end);
		
		//2.获取内存和时间数据集合(此时时间为数据库的时间)
		List<Map<String, Object>> currents = queueChartDao.getMemoryAndDate(qNames,start,end);
//		System.out.println("内存和时间数据集合: " + currents);
		//倒序排列集合
//		Collections.reverse(currents);
		
		
		/** 以下方法可以作为公共的 */
		//返回前端数据Map
		Map<String, List<String>> map = new HashMap<>();
			
		//1)时间集合
		List<String> kpiTimes = getKpiTimes();
		List<String> kpiValues = getKpiData(currents, kpiTimes);
		
//		System.out.println("创建时间集合: " + kpiTimes);
//		System.out.println("内存数据集合: " + kpiValues);
		
		map.put("kpiTimes", kpiTimes);
		map.put("kpiValues", kpiValues);
		return map;
	}
	
	

	/** 4)获取具体队列的磁盘I/O*/
	@Override
	public Map<String, List<String>> getOneDiskIO(String tId, String topicQueueNo) {
		//1.获取send表中多个应用的queueName(list)
		List<String> queueNames = getQueueNameList(topicQueueNo);
		//list转为数组
		String[] qNames =  queueNames.toArray(new String[queueNames.size()]);
		//当前时间 (end)
		Date today = new Date();
		//30分钟后(即当前时间)
		DateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		String end = sdf.format(today);
		//30分钟前时间 (start)
		long times = 35 * 60 * 1000;//35分钟的毫秒值
		Date before = new Date(today.getTime() - times); //35分钟前的时间
		String start = sdf.format(before);

		/**1.时间集合*/
		List<String> kpiTimes = getKpiTimes();
//		System.out.println("创建时间集合: " + kpiTimes);
		
		/**2.获取磁盘读取(I)数据(此时时间为数据库的时间)*/
		List<Map<String, Object>> reads = queueChartDao.getDiskReads(qNames,start,end);
		List<String> readValues = getKpiData(reads, kpiTimes);
//		System.out.println("磁盘读取集合: " + readValues);
		
		
		/**3.获取磁盘写入(O)数据*/
		List<Map<String, Object>> writes = queueChartDao.getDiskWrites(qNames,start,end);
		List<String> writeValues = getKpiData(writes, kpiTimes);
//		System.out.println("磁盘写入集合: " + writeValues);

		Map<String, List<String>> map = new HashMap<>();
			
		
		map.put("kpiTimes", kpiTimes);
		map.put("readValues", readValues);
		map.put("writeValues", writeValues);
		return map;
	}

	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	/**
	 * 5)拓扑图获取应用信息
	 */
	@Override
	public Map<String, Object> getAppInfo(String tId, String topicQueueNo) {
//		System.out.println("根据主键获取拓扑图中应用信息: " + tId);
		//初始化Session中Map
		Map<String, Object> map = new HashMap<>();
		
		/**根据id主键查询主题队列名称*/
		String topicQueueName = topicQueueDao.queryTQName(tId);
//		System.out.println("修改时数据库中主题队列名称: " + topicQueueName + ", 编码: " + topicQueueNo);
		
		map.put("topicQueueNo", topicQueueNo);
		map.put("topicQueueName", topicQueueName);
		
		
		//1)接入信息(根据topicQueueNo获取)
		List<MdApp> oriAppList = topicAccessDao.queryOriAppByQueueSign(topicQueueNo);
		//查询1个源应用并存入session
		if(oriAppList.size() > 0) {
			MdApp oriApp = oriAppList.get(0);
			
			Map<String, String> origin = new HashMap<>();
			if(StringUtils.isNotBlank(oriApp.getId())) {
				origin.put("originId", oriApp.getId());
			}
			if(StringUtils.isNotBlank(oriApp.getAppName())) {
				origin.put("originName", oriApp.getAppName());
			}
			map.put("origin", origin);
		}
		
		//2)发送信息(根据topicQueueNo获取)
		List<Map<String, Object>> targetInfos = topicSendDao.queryTargetAppAndQueueName(topicQueueNo);
//		System.out.println("目标应用targetInfos: " + targetInfos);
		
//		System.out.println("=================以上拓扑图逻辑没问题=========================");
		
		//目标文件名称和kpi集合
		List<Map<String, Object>> tAppList = new ArrayList<>();
		
//		int i = 1;
		//查询多个目标应用
		if(targetInfos.size() > 0) {

			//获取最近的统计时间
			Map<String, Object> tMap = targetInfos.get(0);
			String staticTime = "";
			if(tMap != null) {
				String obj = tMap.get("QUEUE_NAME").toString();
				staticTime = topicSendDao.getStaticTime(obj);
			}
			
			//遍历KPI信息
			for(Map<String, Object> tApp : targetInfos) {
//				System.out.println("第 " + i + " 次遍历目标应用");
				String appName = (String)tApp.get("APP_NAME");

				//一个目标应用信息
				List<Map<String, String>> data = new ArrayList<>();
//				System.out.println("---------------------------------");
				if(StringUtils.isNotBlank(appName)) {
					//一个目标名称和KPI数据集合
					Map<String, Object> oneAppNameAndKpi = new HashMap<>();
					oneAppNameAndKpi.put("name", appName);
					//添加统计时间属性
					oneAppNameAndKpi.put("staticTime", staticTime);
					
					
					//KPI 1.内存堆积(1603) 2.磁盘IO(读1606  写1607) 3.挂起时间(1608)
					if(tApp.get("QUEUE_NAME") != null) {
						String queueName = (String)tApp.get("QUEUE_NAME");
//						System.out.println("queueName即KPI表的OBJ: " + queueName);
						if(StringUtils.isNotBlank(queueName)) {
							
							
							
							//获取KPI数据(只获取当前最近的数据，每个时间点的数据都不一样，无需加总求和)
							List<Map<String, Object>> currents = topicSendDao.getCurrentInfo(queueName);
							
							//单个appKpiData(该map包含4个kpi数据)
							for(Map<String, Object> current : currents) {
								String kpiName = current.get("DICT_NAME").toString();
								String kpiValue = current.get("KPI_VALUE").toString();
//								System.out.println("kpiName: " + kpiName + ", kpiValue: " + kpiValue);
								//转为数值
								String value = "";
								if(kpiName.equals("内存占用")) {
									value = getKpiVal(kpiValue);
									kpiValue = value + " KB";
								}
								if(kpiName.equals("消息堆积量")) {
									value = getKpiVal(kpiValue);
									kpiValue = kpiValue + " 条";
								}
								if(kpiName.equals("磁盘读取")) {
									value = getKpiVal(kpiValue);
									kpiValue = value + " KB";
								}
								if(kpiName.equals("磁盘写入")) {
									value = getKpiVal(kpiValue);
									kpiValue = value + " KB";
								}
								
								//一个目标名称和KPI数据集合
								Map<String, String> oneAppKpi = new HashMap<>();
								//应用名称
								oneAppKpi.put("name", appName);
								//系列名称
								oneAppKpi.put("seriesName", kpiName);
								//传入的数值
								oneAppKpi.put("value", kpiValue);
								//多个应用KPI集合
								data.add(oneAppKpi);
//								System.out.println("=========\n");
							}
							oneAppNameAndKpi.put("data", data);
							//将单个信息放到list中
							tAppList.add(oneAppNameAndKpi);
						}
					}
				}
//				i++;
//				System.out.println();//空一行
			}
		}
		//将目标应用集合tAppInfoList存入map中
		/**
		 * 拓扑图逻辑
		 * 1) tAppList中包含多个map[data[],name], 
		 * 2) map中包含一个data(list类型),
		 * 3) data这个list中包含一个oneAppNameAndKpi(map类型)
		 * 4) oneAppNameAndKpi这个map中包含多个KPI数据
		 */
		map.put("tAppList", tAppList);
//		map.put("tAppInfoList", tAppInfoList);
//		map.put("tAppNameList", tAppNameList);
		
		return map;
	}


	
}
